package xnj.lazydog.btcontroller;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import xnj.lazydog.btcontroller.Bluetooth.BlueToothMaster;
import xnj.lazydog.btcontroller.Bluetooth.BlueToothMaster.BlueToothEventListener;
import xnj.lazydog.btcontroller.ButtonEdit.SendButton;
import xnj.lazydog.btcontroller.ButtonEdit.SendButtonManager;
import xnj.lazydog.btcontroller.ControlViews.DataPackActivity;
import xnj.lazydog.btcontroller.ControlViews.ItemProject;
import xnj.lazydog.btcontroller.ControlViews.LandscapeControlActivity;
import xnj.lazydog.btcontroller.ControlViews.PortraitControlActivity;
import xnj.lazydog.btcontroller.ControlViews.Project;
import xnj.lazydog.btcontroller.ControlViews.ProjectList;
import xnj.lazydog.btcontroller.ControlViews.ScanView;
import xnj.lazydog.btcontroller.HexStringUtils.HexStr;
import xnj.lazydog.btcontroller.MyViews.SwitchButton;
import xnj.lazydog.btcontroller.MyViews.ToolView;
import xnj.lazydog.btcontroller.ObjectFile.ObjectFile;



public class MainActivity extends Activity {

    BlueToothMaster master;
    InputMethodManager inputMethodManager;

    public static MainActivity mainActivity;


    BlueToothEventListener listener = new BlueToothEventListener() {
        @Override
        public void onPowerOn() {

        }
        @Override
        public void onScanningStarted() {

            Log.w("MASTER","scanning started");
            //devices.clear();

        }
        @Override
        public void onScannedDevice(List<BluetoothDevice> devices, BluetoothDevice newDevice) {
            //Log.w("MASTER","scanned");

//            if(device_address!=null)
//            {
//                Log.w(TAG, "onScannedDevice "+isAutoConnect+"  "+device_address);
//            }else
//            {
//                Log.w(TAG, "onScannedDevice past address null");
//            }

            if(isAutoConnect&&device_address!=null&&device_address.length()>5) {
                if (newDevice.getAddress().equals(device_address)) {
                    master.connect(newDevice);
                }
            }
            //MainActivity.devices.add(newDevice);
        }

        @Override
        public void onScanningFinished() {
            scanView.stopScanning();
        }

        @Override
        public void onPaired() {

        }

        @Override
        public void onConnected(BluetoothDevice device) {

            String s = device.getName();
            if(s!=null)
                uiHandler.setDeviceState(s+" 已连接");
            else
                uiHandler.setDeviceState("未知设备" + " 已连接");
            device_address = device.getAddress();

        }

        @Override
        public void onDisConnected() {

            uiHandler.setDeviceState("未连接设备");
        }
        @Override
        public void onPreSend(BlueToothMaster.TxPackage tp) {
        }
        @Override
        public void onDataSent(byte[] b, int l) {
            uiHandler.putTxData(b,l);
        }
        @Override
        public void onReceived(BlueToothMaster.RxPackage rp) {
        }
        @Override
        public void onReceived(byte[] bytes, int length) {
            //Log.w(TAG, "onReceived: "+length );
            uiHandler.putRxData(bytes,length);
        }
        @Override
        public void onStatisticUpdated(BlueToothMaster.Statistic statistic) {
           uiHandler.setStatistic(statistic);
        }
    };

    public class  UIHandler extends Handler
    {
        final int MSG_STATISTIC = 0;
        final int MSG_STATE_CHANGED = 1;
        final int MSG_TX_DATA = 2;
        final int MSG_RX_DATA = 3;
        final int MSG_BUTTON_GO = 4;
        final int MSG_BUTTON_BACK = 5;
        final int MSG_CLEAR_RECORD = 6;
        final int MSG_SHOW_ADD_PRO_DIALOG = 7;
        final int MSG_DEVICE_UUID_DIALOG = 8;
        final int MSG_TOAST = 9;
        final int MSG_UPDATE_SNAP = 10;
        final int MSG_SCROLL_PRO = 11;


        String tx_string;
        String rx_string;
        String go_string;
        String toast_string;

        String back_string;
        boolean isNew;

        BlueToothMaster.Statistic statistic;
        String state;
        void setStatistic(BlueToothMaster.Statistic statistic1)
        {
            statistic =statistic1;
            sendEmptyMessage(MSG_STATISTIC);
        }

        public void toastString(String inf)
        {
            toast_string = inf;
            sendEmptyMessage(MSG_TOAST);
        }

        void clearRecord()
        {
            sendEmptyMessage(MSG_CLEAR_RECORD);
        }
        void setDeviceState(String name)
        {
            state = name;
            sendEmptyMessage(MSG_STATE_CHANGED);
        }

        void putTxData(byte[] b,int l)
        {

            if(isTalk_Hex)
                tx_string = HexStr.bytes2HexStr(b,0,l);
            else
                tx_string = HexStr.bytes2String(b,0,l);


            sendEmptyMessage(MSG_TX_DATA);
        }

        void popGoString(String s)
        {
            go_string = s;
            sendEmptyMessage(MSG_BUTTON_GO);
        }
        void popBackString(String s)
        {
            back_string = s;
            sendEmptyMessage(MSG_BUTTON_BACK);
        }

        void putRxData(byte[] b,int l)
        {
            if(isTalk_Hex)
                rx_string = HexStr.bytes2HexStr(b,0,l);
            else
                rx_string = HexStr.bytes2String(b,0,l);

            if(isButton_HEX)
                popBackString(HexStr.bytes2HexStr(b,0,l));
            else
                popBackString(HexStr.bytes2String(b,0,l));

            sendEmptyMessage(MSG_RX_DATA);
        }

        BluetoothGatt gatt;
        public void showUUIDSettingDialog(BluetoothGatt gatt)
        {
            this.gatt = gatt;
            Log.w(TAG, "showUUIDSettingDialog: UIHANDLER" );
            sendEmptyMessage(MSG_DEVICE_UUID_DIALOG);
        }

        void showAddProjectDialog(boolean b)
        {
            sendEmptyMessageDelayed(MSG_SHOW_ADD_PRO_DIALOG,200);
            isNew = b;
        }


        int project_index;
        //boolean isProScrollSmooth;

        void scrollProjectList(int index)
        {
            project_index = index;
            sendEmptyMessage(MSG_SCROLL_PRO);
        }

        @Override
        public void handleMessage(Message msg) {


            switch (msg.what)
            {
                case MSG_STATISTIC:
                    trans_tx_text.setText("Tx: "+statistic.txRate+"B/s");
                    trans_rx_text.setText("Rx: "+statistic.rxRate+"B/s");
                    trans_err_text.setText("Err: "+statistic.errorRate+"B/s");
                    break;
                case MSG_STATE_CHANGED:
                    device_state_text.setText(state);
                    break;
                case MSG_TX_DATA:

                    if(record_text.getLineCount()>6000)
                        record_text.setText("");
                    record_text.append("<- "+tx_string+"\n");

                    if(isAlwaysNewest) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                recordScrollView.fullScroll(View.FOCUS_DOWN);
                            }
                        });
                    }
                    break;
                case MSG_RX_DATA:
                    if(record_text.getLineCount()>6000)
                        record_text.setText("");
                    record_text.append("-> "+rx_string+"\n");

                    //Log.w(TAG, "handleMessage: MSG RX DATA");
                    if(isAlwaysNewest) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                recordScrollView.fullScroll(View.FOCUS_DOWN);
                            }
                        });

                    }
                    break;
                case MSG_BUTTON_GO:
                    popGoText(go_string);
                    break;
                case MSG_BUTTON_BACK:
                    popBackText(back_string);
                    break;

                case MSG_CLEAR_RECORD:
                    record_text.setText("");
                    break;

                case MSG_SHOW_ADD_PRO_DIALOG :
                    showProjectDialog(isNew);
                    break;
                case MSG_DEVICE_UUID_DIALOG:
                    if(gatt!=null)
                        showUUIDDialog(gatt);
                    break;
                case MSG_TOAST:
                    Toast.makeText(MainActivity.this,toast_string,Toast.LENGTH_SHORT).show();
                    break;
                case MSG_UPDATE_SNAP:
                    //if(projectAdapter!=null)
                    if(projectAdapter!=null) {

                        projectAdapter.notifyDataSetChanged();
                        //projectAdapter.notifyDataSetInvalidated();
                    }
                    break;

                case MSG_SCROLL_PRO:

                    if(projectListView!=null&&project_index<projectListView.getCount())
                    {
                       projectListView.smoothScrollToPosition(project_index);
                    }

                    break;
            }
        }
    }


    class SpinnerDog extends BaseAdapter implements SpinnerAdapter {
        List<String> items = new ArrayList<>();

        public SpinnerDog()
        {
        }

        public void add(String s)
        {
            items.add(s);
            notifyDataSetChanged();
        }

        public void clear()
        {
            items.clear();
            notifyDataSetChanged();
        }

        public void setList(List<String> strings)
        {
            items = new ArrayList<>(strings);
            notifyDataSetChanged();
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            TextView view;
            if(convertView==null)
                view = new TextView(MainActivity.this);
            else
                view = (TextView)convertView;

            view.setTextSize(14);
            view.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
            view.setPadding(0,20,0,20);
            view.setSingleLine(true);
            view.setMaxLines(1);
            view.setTextColor(0xff000000);
            view.setText(items.get(position));
            return view;
        }

        @Override
        public int getCount() {
            return items.size();
        }

        @Override
        public Object getItem(int position) {
            return items.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView view;
            if(convertView==null)
                view = new TextView(MainActivity.this);
            else
                view = (TextView)convertView;
            view.setTextSize(12);
            view.setTextColor(0xff000000);
            view.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
            view.setText(items.get(position));

            return view;
        }

        @Override
        public int getItemViewType(int position) {
            return 0;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public boolean isEmpty() {
            return items.isEmpty();
        }
    };


    int getSameString(List<String> list,String dest)
    {
        int  index = 0;
        for(String str:list)
        {
            Log.w(TAG, "getSameString: "+str+ "---"+dest);
            if(str.equals(dest))
                return index;
            index++;
        }
        return -1;
    }
    AlertDialog uuidDialog;
    String service_uuid="";
    boolean isDeviceUUIDDialogShowing = false;

    public void showUUIDDialog(final BluetoothGatt gatt)
    {

        if(isDeviceUUIDDialogShowing)
            return;
        isDeviceUUIDDialogShowing = true;

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        View v  = LayoutInflater.from(this).inflate(R.layout.device_settings,null);
        builder.setView(v);
        final SpinnerDog serviceAdapter,charTxAdapter,charRxAdapter;
        final Spinner serviceSpinner = v.findViewById(R.id.settings_service);
        final Spinner charTxSpinner = v.findViewById(R.id.settings_char_tx);
        final Spinner charRxSpinner = v.findViewById(R.id.settings_char_rx);
        Button ok = v.findViewById(R.id.settings_device_button);


        serviceAdapter = new SpinnerDog();
        charTxAdapter = new SpinnerDog();
        charRxAdapter = new SpinnerDog();

        serviceSpinner.setAdapter(serviceAdapter);
        charTxSpinner.setAdapter(charTxAdapter);
        charRxSpinner.setAdapter(charRxAdapter);

        final List<String> service_id = new ArrayList<>();
        final List<String> char_id = new ArrayList<>();

        List<BluetoothGattService> services = gatt.getServices();
        for(BluetoothGattService service:services)
        {
            if(service.getCharacteristics().size()>0)
            {
                service_id.add(service.getUuid().toString());
            }
        }
        if(service_id.size()==0)
            service_id.add("无可用Service");

        serviceAdapter.setList(service_id);

        final String [] uuids = master.getUUIDByMAC(gatt.getDevice().getAddress());
        int index = getSameString(service_id,uuids[0]);
        if (index<0)
            index = 0;

        serviceSpinner.setSelection(index);


        serviceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {


                String uuid = service_id.get(position);
                service_uuid = uuid;
                Log.w(TAG, "onItemSelected: "+uuid );
                if(uuid.contains("无可用"))
                    return;

                char_id.clear();

                List<BluetoothGattCharacteristic> characters = gatt.getService(UUID.fromString(uuid)).getCharacteristics();
                for(BluetoothGattCharacteristic characteristic:characters)
                {
                        char_id.add(characteristic.getUuid().toString());
                }
                charTxAdapter.setList(char_id);
                charRxAdapter.setList(char_id);

                int index = getSameString(char_id,uuids[1]);
                if(index<0)
                    index = 0;
                charTxSpinner.setSelection(index);

                index = getSameString(char_id,uuids[2]);
                if(index<0)
                    index = 0;
                charRxSpinner.setSelection(index);
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        charTxSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                Log.w(TAG, "onItemSelected: "+char_id.get(position));

            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        charTxSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                Log.w(TAG, "onItemSelected: "+char_id.get(position));

            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        ok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.w(TAG, "onClick: "+ uuidDialog );
                if(uuidDialog !=null) {
                    //uuidDialog.dismiss();
                    uuidDialog.cancel();
                }
            }
        });
        uuidDialog = builder.create();

        if(uuidDialog.getWindow()!=null)
            uuidDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        uuidDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                //Log.w(TAG, "onDismiss: " );
                isDeviceUUIDDialogShowing = false;
                if(!service_uuid.contains("无可用"))
                {
                    master.putUUID(gatt.getDevice().getAddress(),service_uuid,char_id.get(charTxSpinner.getSelectedItemPosition()),char_id.get(charRxSpinner.getSelectedItemPosition()));
                }
            }
        });

        uuidDialog.show();
        Log.w(TAG, "showUUIDDialog: " );
    }


    UIHandler uiHandler = new UIHandler();


    ScanView scanView;
    TextView device_state_text;
    TextView trans_tx_text,trans_rx_text,trans_err_text;


    List<View> tab_lay = new ArrayList<>();
    List<View> tab_view =new ArrayList<>();
    List<ImageView> tab_img = new ArrayList<>();
    List<Integer> sel_img_id = new ArrayList<>();
    List<Integer> de_sel_img_id = new ArrayList<>();

    private static final String TAG = "MainActivity";
    int lastTabIndex = -1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        //ObjectFile.listAllFiles(this);
        loadOptions();
        initService();

        inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);

        setContentView(R.layout.activity_main);
        device_state_text = findViewById(R.id.bt_state);
        device_state_text.setText("未连接设备");

        trans_tx_text = findViewById(R.id.tx_label);
        trans_rx_text = findViewById(R.id.rx_label);
        trans_err_text = findViewById(R.id.err_label);

        scanView = findViewById(R.id.scanView);
        scanView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(scanView.isGoing) {
                    if(master!=null)
                        master.stopScan();
                    scanView.stopScanning();
                }else {
                    if(master!=null)
                        master.startScan();
                    scanView.startScanning();
                }
            }
        });

        initTalkView();
        initTabViews();
        initSendButton();
        initControlView();
        initSettings();

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("FILE_UPDATE_BUTTON");
        registerReceiver(fileEventReceiver,intentFilter);

        mainActivity = this;
    }

    BroadcastReceiver fileEventReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if("FILE_UPDATE_BUTTON".equals(intent.getAction()))
            {
                Log.w(TAG, "onReceive: File");
                toUpdateProList = true;
                //loadProjectListOptions();
            }
        }
    };


    //// 初始化Service
    BlueToothService.MyBinder binder;
    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.w("SERVICE","connected");
            binder = (BlueToothService.MyBinder)service;
            master=binder.getBTMaster(listener);
            initDeviceListView();

            master.setDeviceFilter(isFilterDevices,namesToFilter);
            master.setWaitMs(waitMs);
            master.uiHandler = uiHandler;
            if(isAutoDiscovery) {
                master.startScan();
                scanView.startScanning();
            }

        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };


    public static boolean toUpdateProList = false;
    @Override
    protected void onResume() {
        super.onResume();

        if(toUpdateProList)
        {
            //loadProjectListOptions();
            loadProjectListUpdate();
            uiHandler.sendEmptyMessage(uiHandler.MSG_UPDATE_SNAP);
            toUpdateProList = false;
        }
        if(projectAdapter!=null&&!projectAdapter.isEmpty())
        {
            new Thread(){
                @Override
                public void run() {

                    try {
                        sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    uiHandler.sendEmptyMessage(uiHandler.MSG_UPDATE_SNAP);
                }
            }.start();


        }

    }

    void initService()
    {
        Intent intent = new Intent(this,BlueToothService.class);
        startService(intent);
        bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
    }


    //// 设备列表实现
    ListView device_list;

    void initDeviceListView()
    {
        device_list = findViewById(R.id.device_listview);
        master.linkListView(device_list,R.layout.device_item,R.drawable.blue,R.drawable.blue_le,R.drawable.rx_circle,R.drawable.tx_circle);
    }


    //// 文本发送功能  ////////////////////////////////////////////////////////////////////////////////

    void sendTalkData()
    {

        if (master.state == BlueToothMaster.STATE_CONNECTED) {
            String s = send_content.getText().toString();

            if(!isTalk_Hex) {
                if (s.length() > 0) {
                    byte[] b;

                    if (turn_line_index > 0) {
                        s = HexStr.replaceTurnLine(s);
                    }

                    b = HexStr.str2Bytes(s);
                    master.pushSend(b, b.length);
                }
            }else
            {
                if(s.length()>0)
                {
                    byte[] b = HexStr.hexStr2Bytes(s);
                    master.pushSend(b,b.length);
                }
            }
        }else {
            //Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show();
            bigSmall(device_state_text);
            setTab(0,false);
        }
    }



    //// 自动发送功能  /////////////////////////////////////////////////////////////////////////////////////////////

    class AutoSendThread extends Thread
    {
        int SLEEP_STEP_MS = 100;
        boolean isAutoSend = false;
        int autoDuration = 1000;
        int autoSendCount = 0;
        int delta = 0;
        boolean isRunning ;
        AutoSendThread()
        {
          super();
          isRunning = true;
        }

        @Override
        public void run() {
            while(isRunning)
            {

                try {
                    if(isAutoSend) {
                        while (autoSendCount < autoDuration) {
                            delta = autoDuration - autoSendCount;

                            if (delta > SLEEP_STEP_MS) {
                                sleep(SLEEP_STEP_MS);
                                autoSendCount += SLEEP_STEP_MS;

                            } else {
                                if(delta>0)
                                sleep(delta);
                                autoSendCount = autoDuration;
                            }
                        }
                        autoSendCount = 0;
                        //Log.w(TAG, "run: auto send ");
                        if(master!=null&&master.state==BlueToothMaster.STATE_CONNECTED)
                        {
                            sendTalkData();
                        }
                    }else
                    {
                        sleep(SLEEP_STEP_MS);
                        autoSendCount = 0;

                    }
                }catch (InterruptedException e)
                {
                    e.printStackTrace();
                }

            }
        }
    }

    AutoSendThread autoSendThread;
    void initAutoSend()
    {

        autoSendThread = new AutoSendThread();
        autoSendThread.start();

    }
    void destroyAutpSend()
    {
        if(autoSendThread!=null) {
            autoSendThread.isRunning = false;
            //autoSendThread.join();
        }
    }

    void startAutoSend(int ms)
    {
        isAutoSend = true;
        autoSendThread.isAutoSend = true;
        autoSendThread.autoDuration = ms;
        autoSendThread.autoSendCount = 0;
    }
    void stopAutoSend()
    {
        isAutoSend = false;
        talk_set.setAutoSend(false);
        autoSendThread.isAutoSend  =false;
    }




    //// 对话视图实现  ////////////////////////////////////////////////////////////////////////////////
    TextView record_text;
    EditText send_content;
    ImageView send_button;
    ImageView clear_all;
    ImageView to_bottom;
    ImageView to_top;
    ScrollView recordScrollView;

    boolean isAlwaysNewest = false;

    ToolView talk_set;
    EditText repeatTime;
    boolean isTalk_Hex = false;
    boolean isAutoSend = false;

    int talkAutoDuration = 1000;

    @SuppressLint("ClickableViewAccessibility")
    void initTalkView()
    {

        initAutoSend();

        record_text = findViewById(R.id.record_text);
        send_content = findViewById(R.id.text_to_send);
        send_button = findViewById(R.id.send_button);
        clear_all = findViewById(R.id.clear_all);
        to_bottom = findViewById(R.id.to_bottom);
        to_top = findViewById(R.id.to_top);
        recordScrollView = findViewById(R.id.record_scroll);

        talk_set = findViewById(R.id.toolView);
        repeatTime = findViewById(R.id.auto_duration);

        String s = ""+talkAutoDuration;
        repeatTime.setText(s);

        repeatTime.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

                int d = HexStr.numberFromString(s,10000,10);

                if(d<0)
                {
                    String str="";
                    if(d==-2)
                    {
                        if(s.length()>0) {
                            for (int i = 0; i < s.length(); i++) {
                                if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
                                    str = str.concat(s.charAt(i) + "");
                                }
                            }
                            repeatTime.setText(str);
                            repeatTime.setSelection(repeatTime.getText().length());
                        }else                                  //// 内容为空
                        {
                            stopAutoSend();
                        }
                    }
                    if(d==-3)    ///// 设置值太小
                    {
                        stopAutoSend();
                        talkAutoDuration = 5;
                        //repeatTime.setText("10");
                        //repeatTime.setSelection(2);
                        //Toast.makeText(MainActivity.this,"间隔太短了",Toast.LENGTH_SHORT).show();
                    }

                    if(d==-4)
                    {
                        repeatTime.setText("10000");
                        repeatTime.setSelection(5);
                        Toast.makeText(MainActivity.this,"间隔太长了",Toast.LENGTH_SHORT).show();
                    }
                }else
                {

                    talkAutoDuration = d;

                    if(isAutoSend)
                    {
                        startAutoSend(d);
                    }

                    Log.w("NUMBER",s.toString()+"  "+d+"   "+isAutoSend);
                }
            }
            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        send_content.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {


                if(isTalk_Hex) {

                    if(HexStr.hasOtherChar(s))
                        Toast.makeText(MainActivity.this,"只能输入0~F的数据",Toast.LENGTH_SHORT).show();

                    if (!HexStr.isHexFormatOK(s.toString())||HexStr.hasLowerCase(s))
                    {
                        String fmtd = HexStr.formatHexString(s.toString());
                        fmtd = fmtd.toUpperCase();
                        send_content.setText(fmtd);

                        //if(s.length()>0)
                        send_content.setSelection(fmtd.length());
                    }
                }
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });

        talk_set.setAutoSend(isAutoSend);
        talk_set.setHexMode(isTalk_Hex);

        talk_set.setOnCheckedListener(new ToolView.OnCheckedListener() {
            @Override
            public void onHexChecked(boolean state) {
                isTalk_Hex = state;
                if(state) {

                    CharSequence s = send_content.getText();

                    s = HexStr.formatHexString(s.toString());

                    send_content.setText(s);
                 //   send_content.setText("");
                }else
                {
                    send_content.setText("");
                }
            }
            @Override
            public void onAutoChecked(boolean state) {

                if(state)
                {
                    if(talkAutoDuration<10)
                    {
                        repeatTime.setText("10");
                        talkAutoDuration = 10;
                        Toast.makeText(MainActivity.this,"最低间隔为10ms",Toast.LENGTH_SHORT).show();
                    }
                    startAutoSend(talkAutoDuration);
                }else
                    stopAutoSend();
            }
        });



        clear_all.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bigSmall(v);
                uiHandler.clearRecord();
            }
        });

        to_bottom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bigSmall(v);
                setRecordScroll(SCROLL_BOT);
            }
        });

        to_top.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bigSmall(v);
                setRecordScroll(SCROLL_TOP);
            }
        });

        send_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send_button.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.shrink_button));
                sendTalkData();
            }
        });



        recordScrollView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if(event.getAction()==MotionEvent.ACTION_MOVE) {
                   // Log.w("DRAG", "" + event.getAction()+recordScrollView.getScrollY()+"   "+recordScrollView.getChildAt(0).getHeight());

                    if (recordScrollView.getScrollY() > recordScrollView.getChildAt(0).getHeight()-recordScrollView.getHeight() - 150)
                        isAlwaysNewest = true;
                    else
                        isAlwaysNewest = false;
                }
                return false;
            }
        });

    }

    final int SCROLL_TOP = 0;
    final int SCROLL_BOT = 1;

    void setRecordScroll(int i)
    {
        if(i==SCROLL_TOP) {
            //record_text.setScrollY(0);
            recordScrollView.fullScroll(View.FOCUS_UP);
            //recordScroll = 0;
            isAlwaysNewest = false;
        }
        else if(i==SCROLL_BOT)
        {
            recordScrollView.fullScroll(View.FOCUS_DOWN);
            //recordScroll = 1000;
            isAlwaysNewest = true;
        }
    }



    void  bigSmall(final View view)
    {
        Animation a = AnimationUtils.loadAnimation(this,R.anim.big_small);
        final Animation b = AnimationUtils.loadAnimation(this,R.anim.big_small_2);

        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
                view.startAnimation(b);
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        view.startAnimation(a);
    }



    //// Button 视图实现  ///////////////////////////////////////////////////////////////////////////
    Button[]  send_buttons = new Button[11];
    SwitchButton button_edit_switch;

    TextView  back_text;
    TextView  go_text;

    boolean isButton_HEX = false;
    SwitchButton button_hex_sb;

    SendButtonManager sendButtonManager;
    void initSendButton()
    {
        send_buttons[0] = findViewById(R.id.send_button1);
        send_buttons[1] = findViewById(R.id.send_button2);
        send_buttons[2] = findViewById(R.id.send_button3);
        send_buttons[3] = findViewById(R.id.send_button4);
        send_buttons[4] = findViewById(R.id.send_button5);
        send_buttons[5] = findViewById(R.id.send_button6);
        send_buttons[6] = findViewById(R.id.send_button7);
        send_buttons[7] = findViewById(R.id.send_button8);
        send_buttons[8] = findViewById(R.id.send_button9);
        send_buttons[9] = findViewById(R.id.send_button10);
        send_buttons[10] = findViewById(R.id.send_button11);

        button_hex_sb = findViewById(R.id.button_display_hex);
        back_text = findViewById(R.id.text_back);
        go_text  = findViewById(R.id.text_go);
        go_text.setText("");
        back_text.setText("未收到消息");
        button_edit_switch = findViewById(R.id.button_edit_switch);
        button_edit_switch.setChecked(false);
        sendButtonManager = new SendButtonManager(this,send_buttons,sharedPreferences,sendButtonEventListener);
        button_edit_switch.setOnCheckedChangedListener(new SwitchButton.OnCheckedChangedListener() {
            @Override
            public void onCheckedChanged(boolean isChecked) {
                sendButtonManager.isEditingButton = isChecked;
            }
        });


        button_hex_sb.setOnCheckedChangedListener(new SwitchButton.OnCheckedChangedListener() {
            @Override
            public void onCheckedChanged(boolean isChecked) {
                isButton_HEX = isChecked;
            }
        });
        button_hex_sb.setCheckImm(isButton_HEX);
    }

    SendButtonManager.SendButtonEventListener sendButtonEventListener = new SendButtonManager.SendButtonEventListener() {
        @Override
        public void onButtonSend(byte[] b,String s) {

            //Log.w("SEND","button send"+new String(data));
            if(master.state==BlueToothMaster.STATE_CONNECTED) {
                if(b.length>0) {

                    master.pushSend(b, b.length);

                    if(isButton_HEX)
                        uiHandler.popGoString(HexStr.bytes2HexStr(b));
                    else
                        uiHandler.popGoString(s);
                }
            }else {
                bigSmall(device_state_text);
                //Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show();
                setTab(0,false);
            }
        }
        @Override
        public void onDialogShow(SendButton sb) {

        }
        @Override
        public void onDialogDismissed(SendButton sb) {
            if(!sendButtonManager.isEditingButton)
                button_edit_switch.setChecked(false);
        }
    };

    void popBackText(String s)
    {
        back_text.setText(s);
        back_text.startAnimation(AnimationUtils.loadAnimation(this,R.anim.popout));
    }
    void popGoText(String s)
    {
        Animation animation = AnimationUtils.loadAnimation(this,R.anim.fadeout);
        go_text.setText(s);
        go_text.setAlpha(1);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }
            @Override
            public void onAnimationEnd(Animation animation) {
                go_text.setAlpha(0);
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        go_text.startAnimation(animation);
    }


    ////  控制视图初始化  ---------------------------------------------------------------------------

    ListView projectListView;
    View extendedView;


    class ProjectAdapter extends ArrayAdapter
    {
        public ProjectAdapter(Context context, int resource,List<ItemProject> objects) {
            super(context, resource, objects);
        }


        @Override
        public View getView(int position,  View convertView,  ViewGroup parent) {
            final View itemView;
            TextView name;
            TextView time;
            ImageView logo,play;
            View edit,views,dataPack,delete,share;
            int cy,cd;
            int py,pd;
            final LinearLayout settings_layout,settings;


            final ItemProject ip = (ItemProject) getItem(position);
            if(convertView==null)
                itemView  = LayoutInflater.from(MainActivity.this).inflate(R.layout.control_view_list_item,null);
            else
                itemView = convertView;

            logo = itemView.findViewById(R.id.project_logo);

            Drawable snap = ObjectFile.getDrawable(ip.fileName+".png");
            if(snap!=null)
                logo.setImageDrawable(snap);
            else {
                if (ip.type == ItemProject.TYPE_PORTRAIT_VIEW)
                    logo.setImageResource(R.drawable.verti_snap);
                else
                    logo.setImageResource(R.drawable.hori_snap);
            }
            name = itemView.findViewById(R.id.project_item_name);
            time = itemView.findViewById(R.id.project_item_time);
            settings_layout = itemView.findViewById(R.id.project_settings_layout);
            settings = itemView.findViewById(R.id.project_settings_trigger_layout);
            play = itemView.findViewById(R.id.project_play);
            edit = itemView.findViewById(R.id.project_item_edit);
            views = itemView.findViewById(R.id.project_item_views);
            dataPack = itemView.findViewById(R.id.project_item_datapack);
            delete = itemView.findViewById(R.id.project_item_delete);
            share = itemView.findViewById(R.id.project_share);


            edit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bigSmall(v);
                    uiHandler.showAddProjectDialog(false);
                }
            });

            views.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bigSmall(v);
                    jumpToControlView(ip,true);
                }
            });

            dataPack.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bigSmall(v);
                    Intent intent;
                    intent = new Intent(MainActivity.this, DataPackActivity.class);
                    intent.putExtra("fileName",ip.fileName);
                    startActivity(intent);
                }
            });

            delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bigSmall(v);
                    showDeleteProjectDialog();
                }
            });

            share.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    File proFile = new File(ObjectFile.extRootDir+"/"+ ip.fileName);
                    //Log.w(TAG, "onClick: "+proFile.getAbsolutePath()+"  "+proFile.exists() );
                    ObjectFile.shareProFile(MainActivity.this,proFile);

                }
            });

            play.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bigSmall(v);

                    Log.w(TAG, "onClick: "+ip.name+"  "+ip.fileName);

                    if(master.state==BlueToothMaster.STATE_CONNECTED)
                        jumpToControlView(ip,false);
                    else {
                        bigSmall(device_state_text);
                        Toast.makeText(MainActivity.this, "请先连接要调试的设备", Toast.LENGTH_SHORT).show();
                        setTab(0,false);
                    }

                }
            });

            settings.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    if(ip!=null) {
                        selectedProject = ip;
                        selectedProjectIndex = projectList.itemProjects.indexOf(selectedProject);
                    }
                    extendedView = itemView;
                    for(int i=0;i<projectListView.getChildCount();i++)
                    {
                        if(extendedView==projectListView.getChildAt(i)) {
                            setSettingsViewVisibility(extendedView, true);
                        }
                        else
                            setSettingsViewVisibility(projectListView.getChildAt(i),false);
                    }
                }
            });

                settings_layout.setVisibility(View.GONE);

            name.setText(ip.name);
            Date currentDate = new Date();
            Date projectDate = new Date(ip.time);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(currentDate);

            cy = calendar.get(Calendar.YEAR);
            cd =calendar.get(Calendar.MONTH);
            cd =cd*100+calendar.get(Calendar.DAY_OF_MONTH);

            calendar.setTime(projectDate);
            py = calendar.get(Calendar.YEAR);
            pd =  calendar.get(Calendar.MONTH);
            pd = pd*100 + calendar.get(Calendar.DAY_OF_MONTH);

            if(cy!=py)
                time.setText(DateFormat.format("yyyy-MM-dd HH:mm打开过",projectDate));
            else if(pd!=cd) {
                if(pd==cd-1)
                    time.setText(DateFormat.format("昨天 HH:mm打开过", projectDate));
                else
                    time.setText(DateFormat.format("MM-dd HH:mm打开过", projectDate));
            }else
                time.setText(DateFormat.format("今天 HH:mm打开过",projectDate));

            return itemView;
        }
    }
    ProjectAdapter projectAdapter ;
    ImageView add_new_button ;
    ProjectList projectList;
    void initControlView()
    {

        loadProjectListOptions();

        ObjectFile.deleteUselessFiles(this,projectList.itemProjects);

        //ObjectFile.listAllFiles(this);

        projectAdapter = new ProjectAdapter(this,R.layout.control_view_list_item,projectList.itemProjects);
        add_new_button = findViewById(R.id.add_new_button);
        projectListView = findViewById(R.id.control_view_listview);
        projectListView.setAdapter(projectAdapter);


        add_new_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bigSmall(v);
                uiHandler.showAddProjectDialog(true);
            }
        });


    }
    void setSettingsViewVisibility(View itemView,boolean toShow)
    {
        final View v = itemView.findViewById(R.id.project_settings_layout);
        if(v!=null)
        {
            if(v.getVisibility()==View.GONE) {
                if(toShow) {
                    Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translate_show);
                    v.setVisibility(View.VISIBLE);
                    v.startAnimation(animation);
                }
            }
            else {
                    if(toShow) {
                        Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translate_hide);
                        animation.setAnimationListener(new Animation.AnimationListener() {
                            @Override
                            public void onAnimationStart(Animation animation) {
                            }
                            @Override
                            public void onAnimationEnd(Animation animation) {
                                v.setVisibility(View.GONE);
                            }
                            @Override
                            public void onAnimationRepeat(Animation animation) {
                            }
                        });
                        v.startAnimation(animation);
                        extendedView = null;
                    }else
                    {
                        v.setVisibility(View.GONE);
                    }
            }
        }
    }

    EditText projectNameEdit;
    RadioGroup projectTypeRadio;
    Button addProjectCancel,addProjectConfirm;
    AlertDialog addProjectDialog;
    ImageView addProjectLogo;
    TextView addProjectName;

    ItemProject selectedProject;
    int selectedProjectIndex;

    int selectedType = 0;

    void showProjectDialog(final boolean isNew)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        View v  = LayoutInflater.from(this).inflate(R.layout.add_project_layout,null);
        addProjectDialog = builder.setView(v).create();
        projectNameEdit = v.findViewById(R.id.project_name);
        projectTypeRadio = v.findViewById(R.id.project_type_radio);
        addProjectCancel = v.findViewById(R.id.project_add_cancel);
        addProjectConfirm = v.findViewById(R.id.project_add_confirm);
        addProjectLogo = v.findViewById(R.id.add_project_logo);
        addProjectName = v.findViewById(R.id.add_project_title);

        if(!isNew)
        {
            addProjectLogo.setImageResource(R.drawable.name);
            addProjectName.setText("修改工程属性");
            projectNameEdit.setText(selectedProject.name);

            projectTypeRadio.check(projectTypeRadio.getChildAt(selectedProject.type).getId());

        }

        projectTypeRadio.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                for(int i=0;i<projectTypeRadio.getChildCount();i++)
                {
                    if(projectTypeRadio.getChildAt(i)==group.findViewById(checkedId))
                        selectedType = i;
                }
            }
        });
        addProjectCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addProjectDialog.dismiss();
            }
        });
        addProjectConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(isNew) {

                    projectList.addProject(MainActivity.this, projectNameEdit.getText().toString(), selectedType);
                    ObjectFile.saveObject(MainActivity.this,"project_list",projectList);
                    projectAdapter.notifyDataSetChanged();
                }
                else {

                    String newName = projectNameEdit.getText().toString();
                    boolean toRename = false;

                    if(!selectedProject.name.equals(newName))
                        toRename = true;

                    if(selectedProject.type!=selectedType)
                        toRename = true;

                    if(toRename) {
                        selectedProject.name = newName;
                        selectedProject.type = selectedType;
                        projectAdapter.notifyDataSetChanged();

                        String newFileName = ObjectFile.getProjectNewFileName(selectedProject.fileName,newName,selectedType);

                        //Log.w(TAG, "onRename: "+selectedProject.fileName+"  "+newFileName );
                        Project p =(Project)ObjectFile.loadObject(MainActivity.this,selectedProject.fileName);
                        //String newFileName = ObjectFile.getProjectNewFileName(selectedProject.fileName,newName,selectedType);
                        ObjectFile.saveObject(MainActivity.this,newFileName,p);
                        selectedProject.fileName = newFileName;
                    }




                }

                addProjectDialog.dismiss();
                if(isNew)
                    uiHandler.scrollProjectList(0);
            }
        });

        int l = projectNameEdit.getText().length();
        projectNameEdit.setSelection(0,l);

        addProjectDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        addProjectDialog.show();

        projectNameEdit.postDelayed(new Runnable() {
            @Override
            public void run() {
                inputMethodManager.showSoftInput(projectNameEdit,InputMethodManager.SHOW_IMPLICIT);
            }
        },400);

    }


    void showDeleteProjectDialog()
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("要删除该工程吗？").setPositiveButton("是", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                projectList.deleteProject(MainActivity.this,selectedProjectIndex);
                ObjectFile.saveObject(MainActivity.this,"project_list",projectList);
                projectAdapter.notifyDataSetChanged();

            }
        }).setNegativeButton("否", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }).create().show();
    }

    void jumpToControlView(ItemProject ip,boolean toDesign)
    {

        final Intent intent;
        ip.time = ObjectFile.getLongTime();
        if(ip.type==0)
            intent = new Intent(MainActivity.this,PortraitControlActivity.class);
        else
            intent = new Intent(MainActivity.this,LandscapeControlActivity.class);
        intent.putExtra("fileName",ip.fileName);
        intent.putExtra("to_design",toDesign);


        Thread thread = new Thread()
        {
            @Override
            public void run() {
                try {
                    sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                startActivity(intent);
            }
        };
        thread.start();

    }

    //// 程序设置相关 //////////////////////////////////////////////////////////////////

    boolean isAutoPowerOn = true;
    boolean isAutoDiscovery = true;
    boolean isAutoConnect = false;
    boolean isFilterDevices = false;
    String  namesToFilter="";
    String  device_address="";

    SwitchButton switch_auto_power_on;
    SwitchButton switch_auto_discovery;
    SwitchButton switch_auto_connect;
    SwitchButton switch_filter_device;
    EditText device_to_filter;

    TextView help_site;

    Spinner turn_line;

    EditText waitMsText;

    RadioGroup codeGroup;

    String charSetName = "utf-8";

    void initSettings() {
        switch_auto_power_on = findViewById(R.id.switch_auto_power_on);
        switch_auto_discovery = findViewById(R.id.switch_auto_discovery);
        switch_auto_connect = findViewById(R.id.switch_auto_connect);
        switch_filter_device = findViewById(R.id.switch_filter_devices);
        device_to_filter = findViewById(R.id.text_device_to_keep);
        help_site = findViewById(R.id.settings_help);
        turn_line = findViewById(R.id.turnline);
        waitMsText = findViewById(R.id.settings_wait_ms);

        waitMsText.setText(""+waitMs);


        codeGroup = findViewById(R.id.code_group);
        codeGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                RadioButton r = findViewById(checkedId);
                if(r!=null) {

                    charSetName = r.getText().toString();
                    HexStr.setCharset(charSetName);

                }
            }
        });

        RadioButton radioButton;
        for(int i=0;i<codeGroup.getChildCount();i++)
        {
            radioButton =(RadioButton) codeGroup.getChildAt(i);
            if(charSetName.equals(radioButton.getText().toString())) {
                radioButton.setChecked(true);
                break;
            }
        }



        waitMsText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
            @Override
            public void afterTextChanged(Editable s) {
                String str = s.toString();
                if(str.length()>0)
                {
                    try{
                        waitMs = Integer.parseInt(str);
                        if(waitMs<10)
                            waitMs =10;
                        if(waitMs>10000)
                            waitMs = 10000;
                        if(master!=null)
                            master.setWaitMs(waitMs);
                    }catch (NumberFormatException ex)
                    {
                        waitMs = 50;
                        waitMsText.setText("50");
                        if(master!=null)
                            master.setWaitMs(waitMs);
                    }
                }
            }
        });


        HexStr.setTurnLine(turn_line_index);
        turn_line.setSelection(turn_line_index);
        turn_line.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                Log.w(TAG, "onItemSelected: "+position);
                turn_line_index = position;
                HexStr.setTurnLine(turn_line_index);
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        help_site.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bigSmall(v);
                Intent intent = new Intent(Intent.ACTION_VIEW);
                //Intent intent = new Intent(Intent.ACTION_VIEW,uri);
                //intent.setAction("android.intent.action.VIEW");
                Uri content_url = Uri.parse("https://www.jianshu.com/u/43ecbce10c64");
                intent.setData(content_url);
                startActivity(intent);
            }
        });

        switch_auto_power_on.setChecked(isAutoPowerOn);
        switch_auto_discovery.setChecked(isAutoDiscovery);
        switch_auto_connect.setChecked(isAutoConnect);
        switch_filter_device.setChecked(isFilterDevices);
        device_to_filter.setText(namesToFilter);
        switch_auto_discovery.thumbOffColor = 0xffdddddd;
        switch_filter_device.thumbOffColor = 0xffdddddd;
        switch_auto_connect.thumbOffColor = 0xffdddddd;

        switch_auto_power_on.setOnCheckedChangedListener(new SwitchButton.OnCheckedChangedListener() {
            @Override
            public void onCheckedChanged(boolean isChecked) {
                isAutoPowerOn = isChecked;
            }
        });
        switch_auto_discovery.setOnCheckedChangedListener(new SwitchButton.OnCheckedChangedListener() {
            @Override
            public void onCheckedChanged(boolean isChecked) {
                isAutoDiscovery = isChecked;
            }
        });
        switch_auto_connect.setOnCheckedChangedListener(new SwitchButton.OnCheckedChangedListener() {
            @Override
            public void onCheckedChanged(boolean isChecked) {
                isAutoConnect = isChecked;
            }
        });
        switch_filter_device.setOnCheckedChangedListener(new SwitchButton.OnCheckedChangedListener() {
            @Override
            public void onCheckedChanged(boolean isChecked) {

                if(!isChecked) {
                    isFilterDevices = false;
                    if(master!=null)
                        master.setDeviceFilter(false,namesToFilter);
                }else
                {
                    if(namesToFilter==null||namesToFilter.equals(""))
                    {
                        Toast.makeText(MainActivity.this,"请输入要连接的设备的名称",Toast.LENGTH_SHORT).show();
                        switch_filter_device.setChecked(false);

                    }else
                    {
                        isFilterDevices = true;
                        if(master!=null)
                            master.setDeviceFilter(true,namesToFilter);
                    }
                }
            }
        });

        device_to_filter.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                namesToFilter = s.toString();
                if(s.length()>0) {


                    if (isFilterDevices) {
                        if(master!=null)
                            master.setDeviceFilter(true, namesToFilter);
                    }

                }else
                {
                    switch_filter_device.setChecked(false);
                    isFilterDevices = false;
                    if(master!=null)
                        master.setDeviceFilter(false, namesToFilter);
                }
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });

    }




    //// 配置加载和存储相关 //////////////////////////////////////////////////////////////
    // 初始化sp

    SharedPreferences sharedPreferences;

    //public static final int TURN_LINE_NONE =0;
    //public static final int TURN_LINE_0A =1;
    //public static final int TURN_LINE_0D =2;
    //public static final int TURN_LINE_0D0A =3;

    final String [] turn_line_list = new String[]{""+'\n',""+'\r',""+'\r'+'\n',""};


    int turn_line_index;
    int waitMs;


    /**
     * 加载一般配置
     */
    void loadOptions()
    {
        sharedPreferences = getSharedPreferences("options",MODE_PRIVATE);
        isAutoPowerOn = sharedPreferences.getBoolean("auto_power_on",true);
        isAutoDiscovery = sharedPreferences.getBoolean("auto_discovery",true);
        isAutoConnect = sharedPreferences.getBoolean("auto_connect",false);
        isFilterDevices = sharedPreferences.getBoolean("auto_filter",false);
        namesToFilter = sharedPreferences.getString("names_to_filter","");
        device_address = sharedPreferences.getString("device_address","");
        turn_line_index = sharedPreferences.getInt("turn_line",0);
        waitMs = sharedPreferences.getInt("wait_ms",80);


        charSetName = sharedPreferences.getString("charset","utf-8");
        HexStr.setCharset(charSetName);


        isButton_HEX = sharedPreferences.getBoolean("button_display_hex",false);

        isTalk_Hex = sharedPreferences.getBoolean("talk_hex",false);
        talkAutoDuration = sharedPreferences.getInt("talk_ms",1000);


        Log.w(TAG, "loadOptions: "+device_address);

    }
    /**
     * 保存一般配置
     */
    void saveOptions()
    {
        sharedPreferences.edit().putBoolean("auto_power_on",isAutoPowerOn)
                .putBoolean("auto_discovery",isAutoDiscovery)
                .putBoolean("auto_connect",isAutoConnect)
                .putBoolean("auto_filter",isFilterDevices)
                .putString("names_to_filter",namesToFilter)
                .putString("device_address",device_address)
                .putInt("turn_line",turn_line_index)
                .putInt("wait_ms",waitMs)
                .putString("charset",charSetName)
                .putBoolean("button_display_hex",isButton_HEX)
                .putBoolean("talk_hex",isTalk_Hex)
                .putInt("talk_ms",talkAutoDuration)
                .apply();
    }
    /**
     * 加载控制视图的配置
     */
    void loadProjectListOptions()
    {
        Log.w(TAG, "loadProjectListOptions: " );
        projectList =(ProjectList) ObjectFile.loadObject(this,"project_list");
        if(projectList==null)
            projectList = new ProjectList();
        ItemProject tip1,tip2;
        for(int i=1;i<projectList.itemProjects.size();i++)
        {
            for(int j=0;j<i;j++) {
                if(projectList.itemProjects.get(j).time<projectList.itemProjects.get(j+1).time)
                {
                    tip2 = projectList.itemProjects.get(j+1);
                    projectList.itemProjects.remove(j+1);
                    projectList.itemProjects.add(j,tip2);
                }
            }
        }


    }


    void loadProjectListUpdate()
    {
        Log.w(TAG, "loadProjectListUpdate: " );
        ProjectList thisProList =(ProjectList) ObjectFile.loadObject(this,"project_list");
        if(thisProList==null)
            thisProList = new ProjectList();

        if(thisProList.itemProjects.size()>projectList.itemProjects.size()) {
            projectList.itemProjects.add(0,thisProList.itemProjects.get(0));
            projectAdapter.notifyDataSetChanged();
        }
    }
    /**
     * 保存控制视图的配置
     */
    void saveProjectListOptions()
    {
        ObjectFile.saveObject(this,"project_list",projectList);
    }

    //// TAB 栏实现
    LinearLayout state_bar;
    View.OnClickListener tablistener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
         setTab(v,false);
        }
    };
    void initTabViews()
    {

        View v = findViewById(R.id.device_lay);

        tab_lay.add(v);
        tab_img.add((ImageView)(findViewById(R.id.device_img)));
        tab_view.add(findViewById(R.id.device_view));
        sel_img_id.add(R.drawable.devices_a);
        de_sel_img_id.add(R.drawable.devices_b);
        
        
        v = findViewById(R.id.talk_lay);
        tab_lay.add(v);
        tab_img.add((ImageView) findViewById(R.id.talk_img));
        tab_view.add(findViewById(R.id.talk_view));
        sel_img_id.add(R.drawable.talk_a);
        de_sel_img_id.add(R.drawable.talk_b);


        v = findViewById(R.id.portrait_lay);
        tab_lay.add(v);
        tab_img.add((ImageView) findViewById(R.id.portrait_img));
        tab_view.add(findViewById(R.id.control_view));
        sel_img_id.add(R.drawable.portrait_a);
        de_sel_img_id.add(R.drawable.portrait_b);


        v = findViewById(R.id.button_lay);
        tab_lay.add(v);
        tab_img.add((ImageView) findViewById(R.id.button_img));
        tab_view.add(findViewById(R.id.button_view));
        sel_img_id.add(R.drawable.button_a);
        de_sel_img_id.add(R.drawable.button_b);

//        v = findViewById(R.id.landscape_lay);
//        tab_lay.add(v);
//        tab_img.add((ImageView) findViewById(R.id.landscape_img));
//        tab_view.add(findViewById(R.id.landscape_view));
//        sel_img_id.add(R.drawable.landscape_a);
//        de_sel_img_id.add(R.drawable.landscape_b);


        state_bar = findViewById(R.id.state_bar);
        state_bar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setTab(tab_lay.get(0),false);
            }
        });

        v = findViewById(R.id.settings_lay);
        tab_lay.add(v);
        tab_img.add((ImageView) findViewById(R.id.settings_img));
        tab_view.add(findViewById(R.id.settings_view));
        sel_img_id.add(R.drawable.settings_a);
        de_sel_img_id.add(R.drawable.settings_b);
        for(View view:tab_lay) {
            view.setOnClickListener(tablistener);

        }
        setTab(tab_lay.get(0),true);
    }

    void setTab(int index,boolean init)
    {
        View v = tab_lay.get(index);
        setTab(v,init);
    }
    void setTab(View v,boolean init)
    {

        int index = tab_lay.indexOf(v);
        if(init)
        {
            for(int i=0;i<tab_lay.size();i++)
            {
                if(v!=tab_lay.get(i)) {

                    tab_view.get(i).setVisibility(View.GONE);
                    tab_img.get(i).setImageResource(sel_img_id.get(i));
                }
            }
        }
        if(index!=lastTabIndex) {

            tab_img.get(index).setImageResource(de_sel_img_id.get(index));
            tab_view.get(index).setVisibility(View.VISIBLE);


            if(lastTabIndex>=0) {
                tab_img.get(lastTabIndex).setImageResource(sel_img_id.get(lastTabIndex));
                //tab_view.get(lastTabIndex).setVisibility(View.GONE);
            }


            comeView(tab_view.get(index),index<lastTabIndex);
            if(lastTabIndex>=0)
            goView(tab_view.get(lastTabIndex),index<lastTabIndex);

        }

        lastTabIndex = index;
    }
    void comeView(View v,boolean from_left)
    {
        if(from_left)
            v.startAnimation(AnimationUtils.loadAnimation(this,R.anim.come_from_left));
        else
            v.startAnimation(AnimationUtils.loadAnimation(this,R.anim.from_right));
    }
    void goView(final View v,boolean to_right)
    {
        Animation animation;
        if(to_right)
            animation = AnimationUtils.loadAnimation(this,R.anim.to_right);
        else
            animation = AnimationUtils.loadAnimation(this,R.anim.to_left);

        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
                v.setVisibility(View.GONE);
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        v.startAnimation(animation);
    }

    //// 退出相关

    @Override
    public void onBackPressed() {

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("是否退出程序？").setPositiveButton("退出", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                quit();
            }
        }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        }).setNeutralButton("后台", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                moveTaskToBack(false);
            }
        }).create().show();
    }

    void quit()
    {
        unbindService(serviceConnection);
        stopService(new Intent(this,BlueToothService.class));
        finish();
    }


    @Override
    protected void onDestroy() {

        unregisterReceiver(fileEventReceiver);
        ReportService.uploadUsage(this);
        destroyAutpSend();
        saveProjectListOptions();
        saveOptions();
        Log.w("DESTROY","activity");
        super.onDestroy();
    }
}
